package com.zhibang.controller;

import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.json.JsonData;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zhibang.config.AlipayConfig;
import com.zhibang.dto.GroupTravelDTO;
import com.zhibang.dto.GroupTravelSearchDTO;
import com.zhibang.entity.GroupTravel;
import com.zhibang.entity.GroupTravelDetail;
import com.zhibang.entity.GroupTravelOrder;
import com.zhibang.entity.Users;
import com.zhibang.service.GroupTravelDetailService;
import com.zhibang.service.GroupTravelOrderService;
import com.zhibang.util.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.highlight.Highlight;
import org.springframework.data.elasticsearch.core.query.highlight.HighlightField;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Tag(name = "团游接口")
@RestController
@RequestMapping("grouptravel")
public class GroupTravelController {
    @Resource
    ElasticsearchTemplate template;

    @RequestMapping("search")
    @Operation(summary = "团游搜索")
    public Result search(@RequestBody GroupTravelSearchDTO dto){
        // 1. 创建查询对象
        BoolQuery.Builder builder = new BoolQuery.Builder();
        // 判断搜索框
        if(StringUtils.isNotBlank(dto.getKeyword())){
            builder.must(m->m.queryString(qs->qs.query(dto.getKeyword())));
        }
        // 旅行方式
        if(StringUtils.isNotBlank(dto.getTravelType())){
            builder.must(m->m.term(qs->qs.field("productTypeName").value(dto.getTravelType())));
        }
        // 团游级别
        if(StringUtils.isNotBlank(dto.getLevel())){
            builder.must(m->m.term(qs->qs.field("level").value(dto.getLevel())));
        }
        // 价格区间
        if(dto.getMinPrice() != null){
            builder.must(m->m.range(qs->qs.field("price").gte(JsonData.of(dto.getMinPrice()))));
        }
        if(dto.getMaxPrice() != null){
            builder.must(m->m.range(qs->qs.field("price").lte(JsonData.of(dto.getMaxPrice()))));
        }
        // 高亮设置
        HighlightField field = new HighlightField("*");
        Highlight highlight = new Highlight(List.of(field));
        HighlightQuery highlightQuery = new HighlightQuery(highlight, GroupTravel.class);
        // 查询构造器
        NativeQueryBuilder nativeQueryBuilder = NativeQuery.builder()
                .withQuery(builder.build()._toQuery())
                .withPageable(PageRequest.of(dto.getPage() - 1, dto.getPageSize()))
                .withHighlightQuery(highlightQuery);
        // 排序
        if("level".equals(dto.getSortType())){
            nativeQueryBuilder.withSort(s->s.field(
              filed->filed.field("level").order(SortOrder.Desc)
            ));
        }
        if("score".equals(dto.getSortType())){
            nativeQueryBuilder.withSort(s->s.field(
                    filed->filed.field("score").order(SortOrder.Desc)
            ));
        }
        if("priceAsc".equals(dto.getSortType())){
            nativeQueryBuilder.withSort(s->s.field(
                    filed->filed.field("price").order(SortOrder.Asc)
            ));
        }
        if("priceDesc".equals(dto.getSortType())){
            nativeQueryBuilder.withSort(s->s.field(
                    filed->filed.field("price").order(SortOrder.Desc)
            ));
        }

        // 查询
        SearchHits<GroupTravel> searchHits = template.search(nativeQueryBuilder.build(), GroupTravel.class);
        List<GroupTravel> docs = new ArrayList<>();
        for (SearchHit<GroupTravel> searchHit : searchHits) {
            GroupTravel doc = searchHit.getContent();
            // 获取高亮结果
            searchHit.getHighlightFields().forEach((k,v)->{
                if("mainName".equals(k)) doc.setMainName(v.get(0));
                if("name".equals(k)) doc.setName(v.get(0));
            });
            docs.add(doc);
        }
        // 创建返回数据
        JSONObject result = new JSONObject();
        result.put("page",dto.getPage());
        result.put("pageSize",dto.getPageSize());
        result.put("total",searchHits.getTotalHits());
        result.put("data",docs);
        return Result.data(result);
    }
    @Resource
    GroupTravelDetailService detailService;
    @RequestMapping("detail")
    @Operation(summary = "团游详情")
    public Result detail(Long id){
        QueryWrapper<GroupTravelDetail> wrapper = new QueryWrapper<>();
        wrapper.eq("pid",id);
        GroupTravelDetail byId = detailService.getOne(wrapper);
        //分割图片
        byId.setImgList(Arrays.asList(byId.getImgs().split(",")));
        return Result.data(byId);

    }
    @Resource
    GroupTravelOrderService orderService;
    @RequestMapping("addOrder")
    @Operation(summary = "团游下单")
    @PreAuthorize("isAuthenticated()")
    public Result addOrder(@RequestBody GroupTravelDTO dto, Authentication auth){
        // 获取用户信息
        Users user = (Users) auth.getPrincipal();
        GroupTravelOrder order=orderService.createOrder(dto,user.getUserId());
        return Result.data(order);
    }
    @Value("${publicIP}")
    String ip;
    @RequestMapping("pay")
    @Operation(summary = "团游支付")
    public Result pay(String orderId,String money) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(
                AlipayConfig.gatewayUrl,
                AlipayConfig.app_id,
                AlipayConfig.merchant_private_key,
                "json",
                AlipayConfig.charset,
                AlipayConfig.alipay_public_key,
                AlipayConfig.sign_type
        );
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();
        model.setOutTradeNo(orderId);
        model.setTotalAmount(money);
        model.setSubject("团游订单支付");
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        //异步通知地址(订单付款成功后跳转到哪里)   必须公网
        request.setNotifyUrl(ip+"/grouptravel/paySuccess");
        request.setBizModel( model);
        AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "Get");
        // 如果需要返回GET请求，请使用
        // AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "GET");
        if (response.isSuccess()) {
            return Result.data(response.getBody());
        } else {
            return Result.fail("下单失败");
        }

    }
    @RequestMapping("paySuccess")
    public void paySuccess(Long out_trade_no){
        //修改订单状态
        System.out.println("监测到有订单已支付:"+out_trade_no);
        GroupTravelOrder order = new GroupTravelOrder();
        order.setOrderId(out_trade_no);
        order.setStatus(2); // 2已支付
        orderService.updateById(order);
    }

}
